#include<vector>
#include<string>
#include<stack>
#include<map>
using namespace std;
class System;
class Page;
class Span;
pair<int,int> Get_Click_Position();
class User{
    public:
        string id;
        string name;
        string pwd;
        bool sex;
        string tele;
        string email;
        virtual int Write()=0;
        // virtual int Show_Infor()=0;
        string ID(){return id;};
        string Name(){return name;};
        string Pwd(){return pwd;};
        string Tele(){return tele;};
        string Email(){return email;};
};
bool Legal_ID(string);
bool Legal_Name(string);
bool Legal_Pwd(string);
bool Legal_Tele(string);
bool Legal_Email(string);

bool Unique_ID(string);
bool Unique_Tele(string);
bool Unique_Email(string);

string Check_By_ID(string );//根据ID返回密码

bool Legal_Company_Name(string);
bool Unique_Company_Name(string);
class Customer: public User{
    private:
    public:
        int Write();
        int Show_Infor();
        void Modify();
        void Modify_Name(int);
        void Modify_Tele(int);
        void Modify_Sex(int);
        void Modify_ID(int);
        void Modify_Email(int);
        void Modify_Pwd(int);
        int Complete();
};
Customer Get_Customer_Infor(string);
class Admin: public User{
    private:
        string company;
    public:
        bool Legal();
        string Company(){return company;};
        int Write();
        int Show_Infor();
        int Modify();
        int Complete();
};
Admin Get_Admin_Infor(string);
class Flight{
    public:
        string flightNumber;
        string company;
        string city[2];
        string modelNumber;
        //机型
        string pilotNames[2];
        string stime;
        //出发时间
        string etime;
        //到达时间
        int remained[3];
        //0为经济舱，1为商务舱，2为头等舱
        int prices[3];
        double punctualityRate;
        //准点率

        void Display(string command);
        //显示航班信息
        int Write();
};
Flight Get_Flight_Infor(string);
bool Legal_Number(string );
bool Unique_Number(string );

//获取数据库中所有航班信息
vector<Flight> Check_All_Flight();

//航班信息过滤
vector<Flight> Filter_Based_On_Company(vector<Flight>,string,bool mode=0);//mode为0时表示只保留该company的航班，为1时表示把该company的航班滤去
vector<Flight> Filter_Based_On_City(vector<Flight>,string,string);
vector<Flight> Filter_Based_On_Stime(vector<Flight>,string stime,bool mode=0);//mode为0时表示只保留起飞时间在mtime之后的航班,为1则相反
vector<Flight> Filter_Based_On_Etime(vector<Flight>,string etime,bool mode=0);//mode为0时表示只保留到达时间在mtime之前的航班,为1则相反，总之0都是正常需要，1都是特殊的相反需要

//航班信息排序
/*
command有
"stime":根据出发时间顺序排列
"etime":根据到达时间顺序排列
"prices":根据最低价格（prices[0]）从低到高
*/
vector<Flight> Flight_Sort(vector<Flight>,string command);
class Page{
    public:
        //把用户在当前页面的字符串类型的输入映射到整数类型的命令
        map<string,int> options;
        //把整数类型的命令映射到指向对应页面的指针
        map<int,Page*> optionsPtr;
        //指向负责渲染当前页面的函数的指针
        int (*funcPtr)(const Page&);
        int translate(string)const ;
        Page();
        //各页面建立联系
        void Ini_Welcome();
        void Ini_Log();
        void Ini_Log_In();
        void Ini_Sign_Up();
        void Ini_Forget();
        void Ini_Home();
        void Ini_Search();
        void Ini_Infor();
        void Ini_Order();
        void Ini_Buy();
        void Ini_Modify();
        
        Span *basis;
        Span *spanPtr[75][250];
        Span *Span_In(pair<int,int>);//返回该坐标对应的span对象
        Span *In_Which(int y,int x);//返回这个位置(y行x列)最顶层的块
        int Count_Layer();

};

void Unable_Quick_Edit_Mode();
void curmove(short,short);
void full_screen();
//各页面的渲染代码
class System{
    public:
        static string User_ID;
        //系统初始化
        Page page;
        stack<Page> sta;
        static int Welcome_Page(const Page&);
        static int Log_Page(const Page&);
        static int Log_In_Page(const Page&);
        static int Sign_Up_Page(const Page&);
        static int Forget_Page(const Page&);
        static int Home_Page(const Page&);
        static int Search_Page(const Page&);
        static int Infor_Page(const Page&);
        static int Order_Page(const Page&);
        static int Buy_Page(const Page&);
        static int Modify_Page(const Page&);
        System();
};
class Order{
    public:
        string Customer_ID;
        string Flight_Number;
        string Order_Time;
};

class Span{
    public:
        pair<int,int> coor;//左上角的坐标
        int wid,hei;
        int layer;
        char ver_bor,hor_bor;//竖直、水平的边框字符
        int type;
        /*
        0无类型
        1文本输入框
        2提交按钮
        3页面切换按钮
        4表单类型
        */
        Span* dad;
        Span* bro;
        Span* son;
        void addson(Span *sonptr){
            if(son==nullptr)son=sonptr;
            else {
                Span *nowptr=son;
                while(nowptr->bro!=nullptr)nowptr=nowptr->bro;
                nowptr->bro=sonptr;
            }
        }
        int cur_x,cur_y;//光标的相对坐标
        void clickaction();//返回这个块是否被点击
        void print();//打印边框
        void setcur();//文本框的点击事件出现或需要输出时把光标移动到相应位置
        IniSpan(int y,int x,int height,int width,char ver='*',char hor='*',bool rel=0,Span *dadspan=nullptr){
            dad=dadspan;
            dadspan.addson(this);
            if(rel){
                coor=make_pair(dadspan->coor.first+y,dadspan->coor.second+x);
            }
            else {
                coor=coord;
            }
            ver_bor=ver;
            hor_bor=hor;
            wid=width;
            hei=height;
        }
};

//鼠标位置